﻿using System.Collections.Generic;
using System.Linq;
using Autodesk.AutoCAD.DatabaseServices;

namespace AutoCADDotNetLibrary
{
    /// <summary>
    /// 块扩展
    /// </summary>
    public static class BlockReferenceExtention
    {
        /// <summary>
        /// 添加块定义
        /// </summary>
        /// <param name="db">dwg数据库</param>
        /// <param name="blockName">块名</param>
        /// <param name="ents">实体集合</param>
        /// <returns></returns>
        public static BlockTableRecord AddBlockTableRecord(this Database db, string blockName, params Entity[] ents)
        {
            BlockTableRecord old = db.GetTableRecord<BlockTableRecord>(blockName, OpenMode.ForWrite);
            if (old != null)
                return old;

            BlockTableRecord btr = db.AddTableRecord<BlockTableRecord>(blockName, tr => ents.ToList().ForEach(x => tr.AppendEntity(x)));
            return btr;
        }

        /// <summary>
        /// 获取指定块名的所有参照
        /// </summary>
        /// <param name="db">dwg数据库</param>
        /// <param name="blockName">块名</param>
        /// <param name="mode">打开模式</param>
        /// <returns>块参照集合</returns>
        public static IEnumerable<BlockReference> GetBlockReferencesByBlockTable(this Database db, string blockName, OpenMode mode)
        {
            BlockTableRecord btr = db.GetTableRecord<BlockTableRecord>(blockName, OpenMode.ForRead);
            ObjectIdCollection blockIds = btr.GetBlockReferenceIds(true, false);

            Transaction trans = db.TransactionManager.TopTransaction;
            return blockIds.Cast<ObjectId>().Select(x => trans.GetObject(x, mode, false, true)).Cast<BlockReference>();
        }

        #region 属性块

        /// <summary>
        /// 块参照添加块中的属性值
        /// </summary>
        /// <param name="blockRef">块参照</param>
        /// <param name="attNameValues">属性数据（Item1:属性，Item2:属性值）</param>
        public static void AddAttributes(this BlockReference blockRef, List<KeyValuePair<string, string>> attNameValues)
        {
            Transaction trans = blockRef.Database.TransactionManager.TopTransaction;
            BlockTableRecord btr = (BlockTableRecord)trans.GetObject(blockRef.BlockTableRecord, OpenMode.ForRead);
            if (!btr.HasAttributeDefinitions)
                return;

            attNameValues = attNameValues?.ToList();
            foreach (ObjectId id in btr)
            {
                AttributeDefinition attDef = trans.GetObject(id, OpenMode.ForRead) as AttributeDefinition;
                if (attDef != null)
                {
                    AttributeReference temp = new AttributeReference();
                    temp.SetAttributeFromBlock(attDef, blockRef.BlockTransform);

                    KeyValuePair<string, string>? first = attNameValues?.FirstOrDefault(x => x.Key == attDef.Tag);
                    if (first.HasValue)
                    {
                        temp.TextString = first.Value.Value;
                        attNameValues.Remove(first.Value);
                    }
                    blockRef.AttributeCollection.AppendAttribute(temp);
                    trans.AddNewlyCreatedDBObject(temp, true);
                }
            }
        }

        /// <summary>
        /// 更新块参照中的属性值
        /// </summary>
        /// <param name="blockRef">块参照</param>
        /// ‘
        /// <param name="attNameValues">属性数据</param>
        public static void UpdateAttributes(this BlockReference blockRef, List<KeyValuePair<string, string>> attNameValues)
        {
            Transaction trans = blockRef.Database.TransactionManager.TopTransaction;

            attNameValues = attNameValues?.ToList();
            foreach (ObjectId id in blockRef.AttributeCollection)
            {
                AttributeReference attref = trans.GetObject(id, OpenMode.ForWrite, false, true) as AttributeReference;

                KeyValuePair<string, string>? first = attNameValues?.FirstOrDefault(x => x.Key == attref.Tag);
                if (first.HasValue)
                {
                    attref.TextString = first.Value.Value.ToString();
                    attNameValues.Remove(first.Value);
                }
            }
        }

        /// <summary>
        /// 获取块参照的属性名和属性值
        /// </summary>
        /// <param name="blockRef">块参照</param>
        /// <returns>属性数据</returns>
        public static List<KeyValuePair<string, string>> GetAttributes(this BlockReference blockRef)
        {
            Transaction trans = blockRef.Database.TransactionManager.TopTransaction;

            List<KeyValuePair<string, string>> attributes = new List<KeyValuePair<string, string>>();
            foreach (ObjectId attId in blockRef.AttributeCollection)
            {
                AttributeReference attRef = (AttributeReference)trans.GetObject(attId, OpenMode.ForRead);
                attributes.Add(new KeyValuePair<string, string>(attRef.Tag, attRef.TextString));
            }
            return attributes;
        }

        #endregion 属性块
    }
}
